//
//  NSObject+Extension.m
//  2016年11月16日21:39:19
//
//  Created by ya on 16/11/22.
//  Copyright © 2016年 ya. All rights reserved.
//

#import "NSObject+Extension.h"
#import <objc/runtime.h>

extern void NotificationCenterPost(NSString *key,
                                   id obj,
                                   NSDictionary *userInfo) {
    [[NSNotificationCenter defaultCenter] postNotificationName:key
                                                        object:obj
                                                      userInfo:userInfo];
}

extern void NotificationCenterAddObserver(id observer,
                                          NSString *key,
                                          SEL sel) {
    [[NSNotificationCenter defaultCenter] addObserver:observer
                                             selector:sel
                                                 name:key
                                               object:nil];
}

extern void NotificationRemoveObserver(id self) {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


extern NSString * DocumentDirectory() {
    return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
}

extern NSString * CachesDirectory() {
    return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
}

extern NSString * TemporaryDirectory() {
    return NSTemporaryDirectory();
}

extern NSString * BundleName() {
    return [NSBundle mainBundle].infoDictionary[@"CFBundleName"];
}


extern NSString * NSStringFromInteger(NSInteger integer) {
    return [NSString stringWithFormat:@"%zd", integer];
}

extern UIImage  * Image(NSString *name) {
    return [UIImage imageNamed:name];
}
















@implementation NSObject (Extension)

- (NSString *)name {
    NSString *name = objc_getAssociatedObject(self, _cmd);
    return name;
}

- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}


+ (instancetype)windowWithRootViewController:(UIViewController *)viewController {
    return ({
        UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        window.backgroundColor = [UIColor whiteColor];
        window.rootViewController = viewController;
        [window makeKeyAndVisible];
        window;
    });
}

- (UIViewController *)viewControllerResponder {
    if ([self isKindOfClass:[UIView class]]) {
        UIView *view = (UIView *)self;
        UIResponder *responder = view.nextResponder;
        while (![responder isKindOfClass:[UIViewController class]]) {
            responder = responder.nextResponder;
        }
        return (UIViewController *)responder;
    }

    return nil;
}

NSArray<__kindof NSLayoutConstraint *> *constraints(UIView *target, NSArray<NSString *> *formats, NSDictionary<NSString *, UIView *> *views) {

    target.translatesAutoresizingMaskIntoConstraints = NO;
    NSMutableArray<NSLayoutConstraint *> *constraintsArrayM = [[NSMutableArray alloc] init];

    for (NSString *format in formats) {
        [constraintsArrayM addObjectsFromArray:({
            [NSLayoutConstraint constraintsWithVisualFormat:format
                                                    options:0
                                                    metrics:nil
                                                      views:views];
        })];
    }

    return constraintsArrayM;
}

+ (NSArray<NSString *> *)getPropertyListNames {
    /**
     *  <#class_copyPropertyList([self class], &outCout)#>
     *  第一个参数: 填入当前对象的类
     *  第二个参数: 填入地址, 用于接收有多少个属性.
     *  该函数的返回值是 所有属性的列表.
     *  return An array of pointers of type \c objc_property_t describing the properties
     */
    NSMutableArray <NSString *> *namesArrM = [NSMutableArray array];
    unsigned int outCout = 0;
    objc_property_t *propertyList = class_copyPropertyList(self, &outCout);

    if (propertyList != NULL && outCout > 0) {
        for (int i = 0; i < outCout; i ++) {
            objc_property_t property = propertyList[i];
            const char *name = property_getName(property);
            NSString *nameStr = [NSString stringWithUTF8String:name];
            [namesArrM addObject:nameStr];
        }
    }

    free(propertyList);
    return namesArrM.copy;
}


+ (NSArray<NSString *> *)getMethodListNames {

    NSMutableArray *methodNamesArrM = [NSMutableArray array];
    unsigned int outCout = 0;
    Method *methodList = class_copyMethodList(self, &outCout);

    if (methodList != NULL && outCout > 0) {
        for (int i = 0; i < outCout; i ++) {
            SEL sel = method_getName(methodList[i]);
            NSString *methodName = NSStringFromSelector(sel);
            [methodNamesArrM addObject:methodName];
        }
    }
    free(methodList);
    return methodNamesArrM.copy;
}


+ (NSArray<NSString *> *)getProtocolListNames {
    NSMutableArray *protocolNamesArrM = [NSMutableArray array];

    unsigned int outCout = 0;
    Protocol * __unsafe_unretained *protocolList = class_copyProtocolList(self, &outCout);
    if (protocolList != NULL && outCout > 0) {
        for (int i = 0; i < outCout; i ++) {
            NSString *protocolName = NSStringFromProtocol(protocolList[i]);
            [protocolNamesArrM addObject:protocolName];
        }
    }

    free(protocolList);
    return protocolNamesArrM.copy;
}
// instance variable
/**
 2016-10-17 19:25:04.065 对象列表Demo[3786:223251] (
 "_testStr",
 "_h1",
 "_h2",
 "_h3",
 "_h4",
 "_h5",
 "_h6"
 )
 */
+ (NSArray<NSString *> *)getInvarListName {

    NSMutableArray *invarListArrM = [NSMutableArray array];

    unsigned int outCout = 0;
    Ivar *ivarList = class_copyIvarList(self, &outCout);
    if (ivarList != NULL && outCout > 0) {
        for (int i = 0; i < outCout; i ++) {
            const char *name = ivar_getName(ivarList[i]);
            NSString *nameStr = [NSString stringWithUTF8String:name];
            [invarListArrM addObject:nameStr];
        }
    }

    free(ivarList);
    return invarListArrM.copy;
}

/// 方法转调用.
//NSInvocation* sj_getMethodInvocationFunc(id target, SEL _cmd, ...) {
//
//    NSMethodSignature *methodSignature = [target methodSignatureForSelector:_cmd];
//    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
//
//    va_list arguments;
//    va_start(arguments, _cmd);
//    NSUInteger count = methodSignature.numberOfArguments;
//    for (int index = 2; index < count ; index ++) { /// 为什么是从2开始, 因为target, _cmd, 已经占坑了, 真实的参数从索引2开始.
//        void *parameter = va_arg(arguments, void *);
//        [invocation setArgument:&parameter atIndex:index];
//    }
//    va_end(arguments);
//
//    invocation.target   = target;
//    invocation.selector = _cmd;
//    return invocation;
//}

__kindof UIView *nibView(NSString *nibName) {
    return [[UINib nibWithNibName:nibName bundle:nil] instantiateWithOwner:nil
                                                                   options:nil].lastObject;
}

UINib *nib(NSString *nibName) {
    return [UINib nibWithNibName:nibName bundle:nil];
}

- (NSObject *(^)(NSObject *))checkObj {

    static NSInteger index = 1;

    return ^NSObject * (NSObject * obj) {
        index ++;
        if (obj == nil || [obj isEqual:@""]) {
            NSLog(@"第%zd个为空!", index);
            obj = @"";
        }
        return obj;
    };
}


@end
